#ifndef GENERICEXCEPTION_HPP
#define GENERICEXCEPTION_HPP

#include <stdexcept>
#include <string>
#include <sstream>

/**
 * Convenience macro to create a GenericException, pre-filled with current file, line, and function
 */
#define GENERICEXCEPTION(text)  GenericException(__FILE__, __LINE__, __PRETTY_FUNCTION__, text)

/**
 * Convenience macro to create and throw a GenericException
 */
#define GENERICSTRMEXCEPTION(stream)  { std::stringstream Strm; Strm << stream; throw GENERICEXCEPTION(Strm.str()); }

/**
 * Convenience macro to create and throw a GenericException if an assertion doesn't hold
 */
#ifdef DEBUG
#define EXCEPTIONASSERTION(assertion, stream)  if (!(assertion)) { std::stringstream Strm; Strm << stream; throw GENERICEXCEPTION(Strm.str()); }
#else
#define EXCEPTIONASSERTION(assertion, stream)
#endif

/**
 * Convenience class for quick-and-dirty exception handling.
 * For even more convenience, use the GENERICEXCEPTION(text) macro for creating instances of this class.
 */
class GenericException : std::exception {

	private:
		std::string location;
		int line;
		std::string function;
		std::string text;

	public:
		GenericException(const std::string &location, int line, const std::string &function, const std::string &text);

		/**
		 * Print this exception on stderr, then terminate program
		 */
		void terminate() const;

		/**
		 * Return the text passed to the constructor
		 */
		std::string getText() const;

		/**
		 * Return the full location, line, function, and text passed to the constructor
		 */
		std::string getFullText() const;

		~GenericException() throw();

	friend std::ostream& operator<<(std::ostream &Strm, const GenericException &Obj);

};


#endif

